/*
 * Jenny Ruppen 09-730-391
 * Sebastien Goldberg 08-914-855
 * Henry Raymond 08-928-061
 * Stefan Mussato 09-752-270
 */
 
package ch.uzh.ifi.sopra.gruppe9.game;

import java.util.ArrayList;
import com.jme3.app.SimpleApplication;
import com.jme3.system.AppSettings;


/**
 * Main class. Initializes game, sets up connection and user interface.
 * Processes game frame update.
 */
public class Game extends SimpleApplication {
	
	
	/**
	 * Toggles debug mode.
	 */
	private static final boolean DEBUG = false;
	
	
	/**
	 * Client-side virtual game board stub.
	 */
	private static GameBoardStub gameBoard;
	
	
	/**
	 * Function calls to be executed at the next update cycle.
	 * (This is needed because the client-side RMI update subscriber is running on
	 * a different thread than jME3, and this can lead to conflicts if the screen 
	 * graph is changed by the update subscriber while it is being rendered.) 
	 */
	private static ArrayList<ICallback> executeAtNextUpdate = new ArrayList<ICallback>();
	
	
	public static void main(String[] args) {
        Game game = new Game();
        game.setSettings(getGraphicsSettings());
        game.start();
        
        // Ensure that the application is terminated when jME3 window closes.
    	game.killWhenClosed();
	}


	@Override
    public void simpleInitApp() {
		
    	// Display frames per second (FPS) for debugging.
    	setDisplayFps(DEBUG);
    	
    	// Display graphics statistics for debugging.
    	setDisplayStatView(DEBUG);
    	
    	// Prevent the game from stopping if the window is not focused.
    	setPauseOnLostFocus(false);
    	
    	// Load all materials
    	MaterialManager.loadAll(assetManager);
    	
    	// Load all fonts
    	Fonts.loadAll(assetManager);
    	
    	// Set up text input
    	TextInput.setup(inputManager);
    	
    	// Set up GUI
    	GUI.setup(this, guiNode, rootNode, inputManager, assetManager, settings.getWidth(), settings.getHeight());
    	
    	// Starts game in GUI
    	GUI.start();
    	
        // Set camera for the in-game scenery.
        Scenery.setCamera(cam, flyCam);
        
        // Set background of in-game scenery.
        viewPort.setBackgroundColor(Scenery.getBackgroundColor());
        
        // Set sun to illuminate the in-game scenery.
        Scenery.setLighting(rootNode, viewPort, assetManager);
    	
    	// Disable standard camera
        flyCam.setEnabled(false);
        flyCam.setMoveSpeed(50);
        
        // Make kuhrsoor visible
        inputManager.setCursorVisible(true);
  
        
        // Force change of state to test state
        //GUI.changeState(GuiState.State.CONSTRUCTION_AUTHORITY);
        //GUI.changeState(GuiState.State.TEST_MAP);
        //GUI.changeState(GuiState.State.TEST_TOWER_ELEMENTS);
        
        //Scenery.createTerrain(2);

    }
    
    
    @Override
    public void simpleUpdate(float tpf) {
		ArrayList<ICallback> currentExecuteAtNextUpdate = new ArrayList<ICallback>();
		currentExecuteAtNextUpdate.addAll(executeAtNextUpdate);
		executeAtNextUpdate.clear();
    	for(ICallback function : currentExecuteAtNextUpdate) {
    		function.run();
    	}
    	GUI.processMouseRollOver();
    	GUI.update(tpf);
    	TextInput.update(tpf);
    }
    
    
    /**
     * Sets client-side virtual game board. (Call this only once the player is connected with the server.)
     */
    public static void setGameBoard(GameBoardStub newGameBoard) {
    	gameBoard = newGameBoard;
    }
    
    
    /**
     * Gets the client-side virtual game board.
     */
    public static GameBoardStub board() {
    	return gameBoard;
    }
    
    
    /**
     * Sets graphics settings, so that the user can't change them.
     */
    private static AppSettings getGraphicsSettings() {
    	AppSettings settings = new AppSettings(true);
    	settings.setTitle("Prot\u00E9g\u00E9s des Kalifen");
    	settings.setResolution(1024, 768);
    	settings.setSettingsDialogImage("/assets/Textures/Splash/splash.png");
    	settings.setFrameRate(60);
		return settings;
	}
    
    
    /**
     * Checks every 2 seconds if jME3 window is still created, and if not, kills the application.
     */
    public void killWhenClosed() {
        try {
        	Thread.sleep(5000);
        	while(context != null && context.isCreated()) {
    			Thread.sleep(2000);
    		}
		} catch (InterruptedException e) {
			e.printStackTrace();
    	}
    	System.exit(1);
    }
    
    
	/**
	 * Adds function calls to be executed at the next update cycle.
	 * (This is needed because the client-side RMI update subscriber is running on
	 * a different thread than jME3, and this can lead to conflicts if the screen 
	 * graph is changed by the update subscriber while it is being rendered.) 
	 */
    public static void executeAtNextUpdate(ICallback function) {
    	executeAtNextUpdate.add(function);
    }

}
